#include "kernel/types.h"
#include "kernel/stat.h"
#include "user.h"

// 待筛数组长度
#define MAXSIZE 36

// 当前是否被筛掉
#define valid   1
#define invalid 0


// 传入管道
void sieve(int* p){
    // 从管道中读取父进程处理过的待筛数组
    int nums[MAXSIZE];
    read(p[0], nums, MAXSIZE*4);

    // 找到第一个有效的数 
    int first_valid = 0;
    for(int i=0; i<MAXSIZE; ++i){
        if(nums[i] == valid){
            first_valid = i;
            break;
        }
    }

    // 若已经筛选完毕
    if(first_valid == 0)    return;

    // 打印当前得到的素数
    printf("prime %d\n", first_valid);

    // 将其倍数的数全都排除出素数
    for(int i=first_valid; i<MAXSIZE; ++i){
        if(i % first_valid == 0)    nums[i] = invalid; 
    }


    // 创建子进程 继续进行筛法
    int pid = fork();
    if(pid < 0){
        printf("failed to fork!\n");
        exit(-1);
    }
    else if(pid > 0){
        write(p[1], nums, MAXSIZE*4);
    }
    else{
        sieve(p);
    }
    wait(0);
}

int main(int argc,char* argv[]){
    //检查参数数量是否正确
    if(argc != 1){
        printf("primes needs not argument!\n"); 
        exit(-1);
    }

    // 待筛数 0-35 初始状态2-35均为有效
    int nums[MAXSIZE];
    nums[0] = nums[1] = invalid;
    for(int i=2; i < MAXSIZE; ++i)  nums[i] = valid;

    // 创建管道
    int p[2];
    pipe(p);

    // 创建子进程 
    int pid = fork();

    // fork失败
    if(pid < 0){
        printf("failed to fork!\n");
        exit(-1);
    }
    // 父进程运行
    else if(pid > 0){
        // 将处理后的数组写进管道，供子进程读取
        write(p[1], nums, MAXSIZE*4);
    }
    // 子进程运行
    else{
        sieve(p);
    }

    wait(0);
    
    exit(0); //确保进程退出
}
